home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / blank / BeyondTheDark.lha / BeyondTheDark / Developer / Source / Maze / Maze.c < prev   
C/C++ Source or Header  |  1995-02-17  |  17KB  |  713 lines

  1.  
  2. #include <exec/memory.h>
  3. #include <exec/execbase.h>
  4. #include <graphics/gfxbase.h>
  5. #include <intuition/intuitionbase.h>
  6. #include <dos/dosextens.h>
  7. #include <libraries/iffparse.h>
  8. #include <utility/tagitem.h>
  9.  
  10. #define __USE_SYSBASE 42
  11.  
  12. #include <proto/dos.h>
  13. #include <proto/exec.h>
  14. #include <proto/graphics.h>
  15. #include <proto/intuition.h>
  16. #include <proto/utility.h>
  17.  
  18. #include <string.h>
  19.  
  20. #include "BTD.h"
  21.  
  22. struct IntuitionBase *IntuitionBase;
  23. struct GfxBase *GfxBase;
  24. struct Library *UtilityBase;
  25. struct DosLibrary *DOSBase;
  26.  
  27. #define MZTAG(o) (BTD_Client+(o))
  28.  
  29. #define MZ_CellSize   MZTAG(0)
  30. #define MZ_SolveDelay MZTAG(1)
  31. #define MZ_Colors     MZTAG(2)
  32.  
  33. #define DEF_CELLSIZE     7
  34. #define DEF_SOLVEDELAY   3
  35. #define DEF_COLORS       2
  36.  
  37. #define MIN_CELLSIZE     3
  38. #define MIN_SOLVEDELAY   0
  39. #define MIN_COLORS       2
  40.  
  41. #define MAX_CELLSIZE    25
  42. #define MAX_SOLVEDELAY  15
  43. #define MAX_COLORS     255
  44.  
  45. struct BTDInteger MazeIntParams[] =
  46.  {
  47.   MZ_CellSize,"Cell Size",BTDPT_INTEGER,DEF_CELLSIZE,MIN_CELLSIZE,MAX_CELLSIZE,TRUE,
  48.   MZ_SolveDelay,"Solve Delay",BTDPT_INTEGER,DEF_SOLVEDELAY,MIN_SOLVEDELAY,MAX_SOLVEDELAY,TRUE,
  49.   MZ_Colors,"Colors",BTDPT_INTEGER,DEF_COLORS,MIN_COLORS,MAX_COLORS,TRUE
  50.  };
  51.  
  52. struct BTDNode *MazeParams[] =
  53.  {
  54.   &MazeIntParams[0].BI_Node,
  55.   &MazeIntParams[1].BI_Node,
  56.   &MazeIntParams[2].BI_Node,
  57.   NULL
  58.  };
  59.  
  60. struct BTDInfo MazeInfo =
  61.  {
  62.   BTDI_Revision,MAKE_ID('M','A','Z','E'),
  63.   "Maze","Maze Blanker","Matthias Scheler",
  64.   MazeParams
  65.  };
  66.  
  67. /* blanker stuff */
  68.  
  69. typedef struct _Stack
  70.  {
  71.   LONG st_x;
  72.   LONG st_y;
  73.   BYTE st_DirOne;
  74.   BYTE st_DirTwo;
  75.   BYTE st_DirThree;
  76.   BYTE st_DirFour;
  77.   struct _Stack *st_Prev;
  78.  } Stack;
  79.  
  80. typedef struct _Maze
  81.  {
  82.   struct BTDDrawInfo *mz_BTDDrawInfo;
  83.   struct RastPort *mz_RPort;
  84.   LONG mz_Left;
  85.   LONG mz_Top;
  86.   LONG mz_Width;
  87.   LONG mz_Height;
  88.   LONG mz_WidStep;
  89.   LONG mz_HeiStep;
  90.   BYTE *mz_Cells;
  91.   BYTE *mz_LeftWalls;
  92.   BYTE *mz_TopWalls;
  93.   Stack *mz_Stack;
  94.   LONG mz_RandN,mz_RandF,mz_RandI;
  95.   LONG mz_StackLength,mz_SolutionLength,mz_NumCols,mz_FirstCol;
  96.   LONG mz_Iter,mz_SolPeriod,mz_SolDelay;
  97.   BYTE mz_Dirs[4];
  98.   BOOL mz_SolveMode;
  99.   Stack *mz_Cell;
  100.   LONG mz_StartY,mz_SolutionY;
  101.  } Maze;
  102.  
  103. #define NORTH 0
  104. #define EAST  1
  105. #define SOUTH 2
  106. #define WEST  3
  107.  
  108. #define HasBeenVisited(Bob,x,y) ((Bob)->mz_Cells[(x)*(Bob)->mz_Height+(y)])
  109. #define Visit(Bob,x,y)          ((Bob)->mz_Cells[(x)*(Bob)->mz_Height+(y)]=1)
  110.  
  111. LONG DirArray[] =
  112.  {
  113.   0x00010203L,0x00010302L,0x00020103L,0x00020301L,0x00030102L,0x00030201L,
  114.   0x01000203L,0x01000302L,0x01020003L,0x01020300L,0x01030002L,0x01030200L,
  115.   0x02000103L,0x02000301L,0x02010003L,0x02010300L,0x02030001L,0x02030100L,
  116.   0x03000102L,0x03000201L,0x03010002L,0x03010200L,0x03020001L,0x03020100L
  117.  };
  118.  
  119. /* rainbow colors */
  120.  
  121. #define NUM_RAINBOW_COLORS 6
  122.  
  123. UBYTE RBRed[NUM_RAINBOW_COLORS+1]   = {0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF};
  124. UBYTE RBGreen[NUM_RAINBOW_COLORS+1] = {0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00};
  125. UBYTE RBBlue[NUM_RAINBOW_COLORS+1]  = {0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00};
  126.  
  127. /* library stuff */
  128.  
  129. char MyBlankerName[] = "maze.btd";
  130. char MyBlankerID[]   = "Maze Blanker V" VERSION "." REVISION " for BTD";
  131.  
  132. LONG MyBlankerLibInit(void)
  133.  
  134. {
  135.  if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  136.   {
  137.    if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
  138.     {
  139.      if (UtilityBase=OpenLibrary("utility.library",37L))
  140.       {
  141.        if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) return TRUE;
  142.  
  143.        CloseLibrary (UtilityBase);
  144.       }
  145.      CloseLibrary (&IntuitionBase->LibNode);
  146.     }
  147.    CloseLibrary (&GfxBase->LibNode);
  148.   }
  149.  return FALSE;
  150. }
  151.  
  152. void MyBlankerLibFree(void)
  153.  
  154. {
  155.  CloseLibrary (&DOSBase->dl_lib);
  156.  CloseLibrary (UtilityBase);
  157.  CloseLibrary (&IntuitionBase->LibNode);
  158.  CloseLibrary (&GfxBase->LibNode);
  159. }
  160.  
  161. /* random generator */
  162.  
  163. void __regargs InitRandom(Maze *Bob,ULONG Instance)
  164.  
  165. {
  166.  ULONG Time[2];
  167.  
  168.  CurrentTime (&Time[0],&Time[1]);
  169.  Bob->mz_RandN=(LONG)Time[0];
  170.  
  171.  if (Time[1]<1024L) Time[1]|=1;
  172.  else Time[1]>>=10;
  173.  Time[1]^=Instance;
  174.  
  175.  Bob->mz_RandF=4*Time[1]+1;
  176.  Bob->mz_RandI=2*Time[1]+1;
  177. }
  178.  
  179. WORD __regargs Random(Maze *Bob,WORD Max)
  180.  
  181. {
  182.  Bob->mz_RandN=Bob->mz_RandF*Bob->mz_RandN+Bob->mz_RandI;
  183.  if (Bob->mz_RandN<0L) Bob->mz_RandN=-Bob->mz_RandN;
  184.  
  185.  return (WORD)(Bob->mz_RandN%Max);
  186. }
  187.  
  188. /* stack handling */
  189.  
  190. Stack __regargs *AllocStack(LONG x,LONG y,BYTE *Directions)
  191.  
  192. {
  193.  Stack *New;
  194.   
  195.  if (New=AllocVec(sizeof(Stack),MEMF_PUBLIC))
  196.   {
  197.    New->st_x=x;
  198.    New->st_y=y;
  199.    (void)memcpy(&New->st_DirOne,Directions,4*sizeof(BYTE));
  200.    New->st_Prev=NULL;
  201.   }
  202.  return New;
  203. }
  204.  
  205. #define Push(b,c) (b)->mz_StackLength++; (c)->st_Prev=(b)->mz_Stack; (b)->mz_Stack=(c)
  206.  
  207. Stack __regargs *Pop(Maze *Bob)
  208.  
  209. {
  210.  Stack *Popped;
  211.     
  212.  if (Popped=Bob->mz_Stack)
  213.   {
  214.    Bob->mz_StackLength--;
  215.    Bob->mz_Stack=Popped->st_Prev;
  216.   }
  217.  return Popped;
  218. }
  219.  
  220. void __regargs FreeMaze(Maze *Bob)
  221.  
  222. {
  223.  if (Bob->mz_Cells) FreeVec (Bob->mz_Cells);
  224.  if (Bob->mz_LeftWalls) FreeVec (Bob->mz_LeftWalls);
  225.  if (Bob->mz_TopWalls) FreeVec (Bob->mz_TopWalls);
  226.  FreeVec (Bob);
  227. }
  228.  
  229. /* maze handling */
  230.  
  231. Maze __regargs *AllocMaze(struct BTDDrawInfo *BTDDrawInfo,LONG Width,LONG Height)
  232.  
  233. {
  234.  Maze *New;
  235.   
  236.  if (New=AllocVec(sizeof(Maze),MEMF_PUBLIC|MEMF_CLEAR))
  237.   {
  238.    New->mz_BTDDrawInfo=BTDDrawInfo;
  239.    New->mz_RPort=BTDDrawInfo->BDI_RPort;
  240.    New->mz_Left=BTDDrawInfo->BDI_Left;
  241.    New->mz_Top=BTDDrawInfo->BDI_Top;
  242.    New->mz_Width=Width;
  243.    New->mz_Height=Height;
  244.    New->mz_WidStep=(BTDDrawInfo->BDI_Width-1)/Width;
  245.    New->mz_HeiStep=(BTDDrawInfo->BDI_Height-1)/Height;
  246.    New->mz_Cells=AllocVec(sizeof(BYTE)*Width*Height,MEMF_PUBLIC|MEMF_CLEAR);
  247.    New->mz_LeftWalls=AllocVec(sizeof(BYTE)*(Width+1)*Height,MEMF_PUBLIC|MEMF_CLEAR);
  248.    New->mz_TopWalls=AllocVec(sizeof(BYTE)*Width*(Height+1),MEMF_PUBLIC|MEMF_CLEAR);
  249.    
  250.    if (New->mz_Cells&&New->mz_LeftWalls&&New->mz_TopWalls) return New;
  251.    
  252.    FreeMaze (New);
  253.   }
  254.  return NULL;
  255. }
  256.  
  257. #define ActivateLeftWall(x,y) (Bob->mz_LeftWalls[(x)*Bob->mz_Height+(y)]=1)
  258. #define ActivateTopWall(x,y)  (Bob->mz_TopWalls[(x)*Bob->mz_Height+(y)]=1)
  259.  
  260. #define LeftWallActive(x,y) (Bob->mz_LeftWalls[(x)*Bob->mz_Height+(y)])
  261. #define TopWallActive(x,y)  (Bob->mz_TopWalls[(x)*Bob->mz_Height+(y)])
  262.  
  263. void __regargs AddHorizWall(Maze *Bob,LONG x,LONG y)
  264.  
  265. {
  266.  Move (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
  267.  Draw (Bob->mz_RPort,Bob->mz_Left+(x+1)*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
  268. }
  269.  
  270. void __regargs AddVertWall(Maze *Bob,LONG x,LONG y)
  271.  
  272. {
  273.  Move (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+y*Bob->mz_HeiStep);
  274.  Draw (Bob->mz_RPort,Bob->mz_Left+x*Bob->mz_WidStep,Bob->mz_Top+(y+1)*Bob->mz_HeiStep);
  275. }
  276.  
  277. void __regargs DrawSolution(Maze *Bob,LONG x,LONG y,LONG Pen,LONG Trailer)
  278.  
  279. {
  280.  SetAPen (Bob->mz_RPort,Pen?Bob->mz_BTDDrawInfo->BDI_Pens[Pen-1]:BTD_BgPen);
  281.  
  282.  switch (Trailer)
  283.   {
  284.    case NORTH:
  285.     RectFill (Bob->mz_RPort,
  286.               Bob->mz_Left+x*Bob->mz_WidStep+1,
  287.               Bob->mz_Top+y*Bob->mz_HeiStep+1,
  288.               Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
  289.               Bob->mz_Top+(y+1)*Bob->mz_HeiStep);
  290.     break;
  291.    case SOUTH:
  292.     RectFill (Bob->mz_RPort,
  293.               Bob->mz_Left+x*Bob->mz_WidStep+1,
  294.               Bob->mz_Top+y*Bob->mz_HeiStep,
  295.               Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
  296.               Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
  297.     break;
  298.    case EAST:
  299.     RectFill (Bob->mz_RPort,
  300.               Bob->mz_Left+x*Bob->mz_WidStep+1,
  301.               Bob->mz_Top+y*Bob->mz_HeiStep+1,
  302.               Bob->mz_Left+(x+1)*Bob->mz_WidStep,
  303.               Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
  304.     break;
  305.    case WEST:
  306.     RectFill (Bob->mz_RPort,
  307.               Bob->mz_Left+x*Bob->mz_WidStep,
  308.               Bob->mz_Top+y*Bob->mz_HeiStep+1,
  309.               Bob->mz_Left+(x+1)*Bob->mz_WidStep-1,
  310.               Bob->mz_Top+(y+1)*Bob->mz_HeiStep-1);
  311.   }
  312.  
  313.  if ((++Bob->mz_Iter%Bob->mz_SolPeriod)==0L) Delay (Bob->mz_SolDelay);
  314. }
  315.  
  316. BYTE __regargs *RemoveDir(Maze *Bob,BYTE *Dir,BYTE RemMe)
  317.  
  318. {
  319.  ULONG Index;
  320.   
  321.  for (Index=0L; Index<4L; Index++)
  322.   Bob->mz_Dirs[Index]=(Dir[Index]==RemMe)?4:Dir[Index];
  323.   
  324.  return Bob->mz_Dirs;
  325. }
  326.  
  327. #define DefRemDir(x) RemoveDir(Bob,(BYTE*)&DirArray[Random(Bob,24)],x)
  328.  
  329. Stack __regargs *GoDirection(Maze *Bob,Stack *Cell,BYTE DirNum)
  330.  
  331. {
  332.  LONG x,y;
  333.  BYTE Direction;
  334.  
  335.  x=Cell->st_x;
  336.  y=Cell->st_y;
  337.  
  338.  switch (DirNum)
  339.   {
  340.    case 0:
  341.     Direction=Cell->st_DirOne;
  342.     Cell->st_DirOne=4;
  343.     break;
  344.    case 1:
  345.     Direction=Cell->st_DirTwo;
  346.     Cell->st_DirTwo=4;
  347.     break;
  348.    case 2:
  349.     Direction=Cell->st_DirThree;
  350.     Cell->st_DirThree=4;
  351.     break;
  352.    case 3:
  353.     Direction=Cell->st_DirFour;
  354.     Cell->st_DirFour=4;
  355.    }
  356.   
  357.  switch( Direction )
  358.   {
  359.    case EAST:
  360.     if (x<(Bob->mz_Width-1))
  361.      if (!HasBeenVisited(Bob,x+1,y))
  362.       {
  363.        Push (Bob,Cell);
  364.        return AllocStack(x+1,y,DefRemDir(WEST));
  365.       }
  366.      else
  367.       {
  368.        AddVertWall (Bob,x+1,y);
  369.        ActivateLeftWall (x+1,y);
  370.       }
  371.     break;
  372.    case NORTH:
  373.     if (y<(Bob->mz_Height-1))
  374.      if (!HasBeenVisited( Bob,x,y+1))
  375.       {
  376.        Push (Bob,Cell);
  377.        return AllocStack(x,y+1,DefRemDir(SOUTH));
  378.       }
  379.      else
  380.       {
  381.        AddHorizWall (Bob,x,y+1);
  382.        ActivateTopWall (x,y+1);
  383.       }
  384.     break;
  385.    case WEST:
  386.     if (x>0)
  387.      if (!HasBeenVisited(Bob,x-1,y))
  388.       {
  389.        Push (Bob,Cell);
  390.        return AllocStack(x-1,y,DefRemDir(EAST));
  391.       }
  392.      else
  393.       {
  394.        AddVertWall (Bob,x,y);
  395.        ActivateLeftWall (x,y);
  396.       }
  397.     break;
  398.    case SOUTH:
  399.     if (y>0)
  400.      if (!HasBeenVisited(Bob,x,y-1))
  401.       {
  402.        Push (Bob,Cell);
  403.        return AllocStack(x,y-1,DefRemDir(NORTH));
  404.       }
  405.      else
  406.       {
  407.        AddHorizWall (Bob,x,y);
  408.        ActivateTopWall (x,y);
  409.       }
  410.   }
  411.  
  412.  return NULL;
  413. }
  414.  
  415. void __regargs ConstructMaze(Maze *Bob,LONG x,LONG y,LONG sx,LONG sy)
  416.  
  417. {
  418.  Stack *Cell,*NewCell;
  419.  
  420.  if ((Cell=Bob->mz_Cell)==NULL) Cell=AllocStack(x,y,(BYTE *)&DirArray[Random(Bob,24)]);
  421.  
  422.  if ((Cell->st_x==sx)&&(Cell->st_y==sy)&&(Bob->mz_SolutionLength==0L))
  423.   Bob->mz_SolutionLength=Bob->mz_StackLength;
  424.  
  425.  Visit (Bob,Cell->st_x,Cell->st_y);
  426.     
  427.  if (NewCell=GoDirection(Bob,Cell,0)) Cell=NewCell;
  428.  else    
  429.   if (NewCell=GoDirection(Bob,Cell,1)) Cell=NewCell;
  430.   else    
  431.    if (NewCell=GoDirection(Bob,Cell,2)) Cell=NewCell;
  432.    else
  433.     if (NewCell=GoDirection(Bob,Cell,3)) Cell=NewCell;
  434.     else
  435.      {    
  436.       FreeVec (Cell);
  437.       Cell=Pop(Bob);
  438.      }
  439.  
  440.  Bob->mz_Cell=Cell;
  441. }
  442.  
  443. Stack __regargs *SolveDirection(Maze *Bob,Stack *Cell,BYTE DirNum)
  444.  
  445. {
  446.  LONG x,y,Pen;
  447.  BYTE Direction;
  448.  
  449.  x=Cell->st_x;
  450.  y=Cell->st_y;
  451.  switch (DirNum)
  452.   {
  453.    case 0:
  454.     Direction=Cell->st_DirOne;
  455.     Cell->st_DirOne=4;
  456.     break;
  457.    case 1:
  458.     Direction=Cell->st_DirTwo;
  459.     Cell->st_DirTwo=4;
  460.     break;
  461.    case 2:
  462.     Direction=Cell->st_DirThree;
  463.     Cell->st_DirThree=4;
  464.     break;
  465.    case 3:
  466.     Direction=Cell->st_DirFour;
  467.     Cell->st_DirFour=4;
  468.   }
  469.  
  470.  Pen=((Bob->mz_StackLength*Bob->mz_NumCols/Bob->mz_SolutionLength+Bob->mz_FirstCol)%Bob->mz_NumCols)+1L;
  471.  switch (Direction)
  472.   {
  473.    case EAST:
  474.     if (x<(Bob->mz_Width-1))
  475.      if (!LeftWallActive(x+1,y))
  476.       {
  477.        Push (Bob,Cell);
  478.        DrawSolution (Bob,x+1,y,Pen,WEST);
  479.        return AllocStack(x+1,y,DefRemDir(WEST));
  480.       }
  481.     break;
  482.    case NORTH:
  483.     if (y<(Bob->mz_Height-1))
  484.      if (!TopWallActive(x,y+1))
  485.       {
  486.        Push (Bob,Cell);
  487.        DrawSolution (Bob,x,y+1,Pen,SOUTH);
  488.        return AllocStack(x,y+1,DefRemDir(SOUTH));
  489.       }
  490.     break;
  491.    case WEST:
  492.     if (x>0)
  493.      if (!LeftWallActive(x,y))
  494.       {
  495.        Push (Bob,Cell);
  496.        DrawSolution (Bob,x-1,y,Pen,EAST);
  497.        return AllocStack(x-1,y,DefRemDir(EAST));
  498.       }
  499.     break;
  500.    case SOUTH:
  501.     if (y>0)
  502.      if (!TopWallActive(x,y))
  503.       {
  504.        Push (Bob,Cell);
  505.        DrawSolution (Bob,x,y-1,Pen,NORTH);
  506.        return AllocStack(x,y-1,DefRemDir(NORTH));
  507.       }
  508.   }
  509.  
  510.  return NULL;
  511. }
  512.  
  513. void __regargs SolveMaze(Maze *Bob,LONG x,LONG y,LONG sx,LONG sy)
  514.  
  515. {
  516.  Stack *Cell,*NewCell;
  517.  
  518.  if ((Cell=Bob->mz_Cell)==NULL) Cell=AllocStack(x,y,(BYTE *)&DirArray[Random(Bob,24)]);
  519.   
  520.  if ((Cell->st_x==sx)&&(Cell->st_y==sy))
  521.   do FreeVec (Cell);
  522.   while (Cell=Pop(Bob));
  523.  else
  524.   if (NewCell=SolveDirection(Bob,Cell,0)) Cell=NewCell;
  525.   else    
  526.    if (NewCell=SolveDirection(Bob,Cell,1)) Cell=NewCell;
  527.    else    
  528.     if (NewCell=SolveDirection(Bob,Cell,2)) Cell=NewCell;
  529.     else    
  530.      if (NewCell=SolveDirection(Bob,Cell,3)) Cell=NewCell;
  531.      else
  532.       {    
  533.        x=Cell->st_x;
  534.        y=Cell->st_y;
  535.  
  536.        FreeVec (Cell);
  537.        Cell=Pop(Bob);
  538.  
  539.        if (Cell->st_x>x) DrawSolution (Bob,x,y,0,EAST);
  540.        if (Cell->st_x<x) DrawSolution (Bob,x,y,0,WEST);
  541.        if (Cell->st_y>y) DrawSolution (Bob,x,y,0,NORTH);
  542.        if (Cell->st_y<y) DrawSolution (Bob,x,y,0,SOUTH);
  543.       }
  544.  
  545.  Bob->mz_Cell=Cell;
  546. }
  547.  
  548. /* implementation of library functions */
  549.  
  550. struct BTDInfo *QueryMyBlanker(void)
  551.  
  552. {
  553.  return &MazeInfo;
  554. }
  555.  
  556. Maze *InitMyBlanker(struct TagItem *TagList)
  557.  
  558. {
  559.  struct BTDDrawInfo *BTDDrawInfo;
  560.  ULONG *Error,Dummy;
  561.  LONG CellSize,SolveDelay,Index;
  562.  Maze *Bob;
  563.  
  564.  if ((BTDDrawInfo=(struct BTDDrawInfo *)
  565.                    GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
  566.  Error=(ULONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);
  567.  
  568.  CellSize=GetTagData(MZ_CellSize,DEF_CELLSIZE,TagList);
  569.  if ((BTDDrawInfo->BDI_Width<(CellSize*4+1))||
  570.      (BTDDrawInfo->BDI_Height<(CellSize*4+1)))
  571.   {
  572.    *Error=BTDERR_Size;
  573.    return NULL;
  574.   }
  575.  
  576.  if ((Bob=AllocMaze(BTDDrawInfo,
  577.                     (BTDDrawInfo->BDI_Width-1)/CellSize,
  578.                     (BTDDrawInfo->BDI_Height-1)/CellSize))==NULL)
  579.   {
  580.    *Error=BTDERR_Memory;
  581.    return NULL;
  582.   }
  583.  
  584.  InitRandom (Bob,GetTagData(BTD_Instance,0L,TagList));
  585.  
  586.  SolveDelay=GetTagData(MZ_SolveDelay,DEF_SOLVEDELAY,TagList);
  587.  if (SolveDelay==0L)
  588.   {
  589.    Bob->mz_SolDelay=0L;
  590.    Bob->mz_SolPeriod=100L;
  591.   }
  592.  else
  593.   if (SolveDelay<12L)
  594.    {
  595.     Bob->mz_SolDelay=1L;
  596.     Bob->mz_SolPeriod=12L-SolveDelay;
  597.    }
  598.   else
  599.    {
  600.     Bob->mz_SolDelay=SolveDelay-10L;
  601.     Bob->mz_SolPeriod=1L;
  602.    }
  603.  
  604.  Bob->mz_NumCols=GetTagData(MZ_Colors,DEF_COLORS,TagList);
  605.  if (Bob->mz_NumCols>NUM_RAINBOW_COLORS)
  606.   {
  607.    LONG ColNum,Col,RBCol;
  608.    UBYTE *Red,*Green,*Blue,*Changed;
  609.  
  610.    Red=BTDDrawInfo->BDI_Red;
  611.    Green=BTDDrawInfo->BDI_Green;
  612.    Blue=BTDDrawInfo->BDI_Blue;
  613.    Changed=BTDDrawInfo->BDI_Changed;
  614.    ColNum=Bob->mz_NumCols/NUM_RAINBOW_COLORS+1L;
  615.    Index=0L;
  616.    for (RBCol=0L; RBCol<NUM_RAINBOW_COLORS; RBCol++)
  617.     {
  618.      if (RBCol==(Bob->mz_NumCols%NUM_RAINBOW_COLORS)) ColNum--;
  619.  
  620.      for (Col=0L; Col<ColNum; Col++)
  621.       {
  622.        Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[RBCol]+((RBRed[RBCol+1]-RBRed[RBCol])*Col)/ColNum;
  623.        Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[RBCol]+((RBGreen[RBCol+1]-RBGreen[RBCol])*Col)/ColNum;
  624.        Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[RBCol]+((RBBlue[RBCol+1]-RBBlue[RBCol])*Col)/ColNum;
  625.        Changed[BTDDrawInfo->BDI_Pens[Index++]]=TRUE;
  626.       }
  627.     }
  628.   }
  629.  else
  630.   for (Index=0L; Index<Bob->mz_NumCols; Index++)
  631.    {
  632.     BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=RBRed[Index];
  633.     BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=RBGreen[Index];
  634.     BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=RBBlue[Index];
  635.     BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  636.    }
  637.  
  638.  return Bob;
  639. }
  640.  
  641. void AnimMyBlanker(Maze *Bob)
  642.  
  643. {
  644.  if (Bob->mz_SolveMode)
  645.   {
  646.    SolveMaze (Bob,0,Bob->mz_StartY,Bob->mz_Width-1,Bob->mz_SolutionY);
  647.    if (Bob->mz_Cell==NULL)
  648.     {
  649.      ULONG Index;
  650.  
  651.      Bob->mz_SolveMode=FALSE;
  652.  
  653.      for (Index=0L; Index<(Bob->mz_Width*Bob->mz_Height); Index++)
  654.       Bob->mz_Cells[Index]=0;
  655.  
  656.      for (Index=0L; Index<((Bob->mz_Width+1)*Bob->mz_Height); Index++)
  657.       Bob->mz_LeftWalls[Index]=0;
  658.      
  659.      for (Index=0L; Index<(Bob->mz_Width*(Bob->mz_Height+1)); Index++)
  660.       Bob->mz_TopWalls[Index]=0;
  661.     }
  662.   }
  663.  else
  664.   {
  665.    if (Bob->mz_Cell==NULL)
  666.     {
  667.      EraseRect (Bob->mz_RPort,
  668.                 Bob->mz_Left,Bob->mz_Top,
  669.                 Bob->mz_Left+Bob->mz_BTDDrawInfo->BDI_Width-1,
  670.                 Bob->mz_Top+Bob->mz_BTDDrawInfo->BDI_Height-1);
  671.  
  672.      SetAPen (Bob->mz_RPort,Bob->mz_BTDDrawInfo->BDI_Pens[Random(Bob,Bob->mz_NumCols)]);
  673.      Move (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top);
  674.      Draw (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top+Bob->mz_Height*Bob->mz_HeiStep );
  675.      Draw (Bob->mz_RPort,Bob->mz_Left+Bob->mz_Width*Bob->mz_WidStep,
  676.            Bob->mz_Top+Bob->mz_Height*Bob->mz_HeiStep);
  677.      Draw (Bob->mz_RPort,Bob->mz_Left+Bob->mz_Width*Bob->mz_WidStep,Bob->mz_Top);
  678.      Draw (Bob->mz_RPort,Bob->mz_Left,Bob->mz_Top);
  679.  
  680.      Bob->mz_StackLength=0L;
  681.      Bob->mz_SolutionLength=0L;
  682.  
  683.      Bob->mz_StartY=Random(Bob,Bob->mz_Height);
  684.      Bob->mz_SolutionY=Random(Bob,Bob->mz_Height);
  685.     }
  686.  
  687.    ConstructMaze(Bob,0,Bob->mz_StartY,Bob->mz_Width-1,Bob->mz_SolutionY);
  688.    if (Bob->mz_Cell==NULL)
  689.     {
  690.      Bob->mz_SolveMode=TRUE;
  691.  
  692.      Bob->mz_FirstCol=Random(Bob,Bob->mz_NumCols);
  693.      DrawSolution (Bob,0,Bob->mz_StartY,Bob->mz_FirstCol+1L,WEST);
  694.      DrawSolution (Bob,Bob->mz_Width-1,Bob->mz_SolutionY,Bob->mz_FirstCol+1L,EAST);
  695.     }
  696.   }
  697. }
  698.  
  699. void EndMyBlanker(Maze *Bob)
  700.  
  701. {
  702.  Stack *Cell;
  703.  
  704.  while (Cell=Pop(Bob)) FreeVec (Cell);
  705.  FreeMaze (Bob);
  706. }
  707.  
  708. ULONG PenCountMyBlanker(struct TagItem *TagList)
  709.  
  710. {
  711.  return GetTagData(MZ_Colors,DEF_COLORS,TagList);
  712. }
  713.